﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Globalization;
using WebUI.SmartDatingRef;
using SvcUtils;
using System.Text.RegularExpressions;

namespace WebUI {
    public partial class Personal : BasePage {
        protected int zSign;
        protected SmartDatingRef.PersonalData pd;

        protected void Page_Load(object sender, EventArgs e) {
            if (Page.IsAsync || Page.IsPostBack) return;

            ResultWithStatusOfstring resGetPd = Client.GetPersonalData(SessionKeyHash);

            if (Status.SUCCESS(resGetPd.Status)) {
                pd = CryptoImpl.readObjectEncrypted<SmartDatingRef.PersonalData>(
                    b(resGetPd.Result), b(SessionKey));
            } else if (resGetPd.Status == OperationStatus.NoPersonalData) {
                DateTime dob = DateTime.UtcNow.Subtract(new TimeSpan(365 * 20, 0, 0, 0, 0));
                pd = new SmartDatingRef.PersonalData() {
                    first_name = "Хтоя",
                    gender = 0,
                    date_of_birth = dob,
                    orientation = 0,
                    reason = 0,
                    interests = "интересы,через,запятую",
                    bio = "Кратко обо мне: ...",
                    zodiac = dob.Month - 1
                };
            } else {
                Utils.showError(errSpan, Status.m(resGetPd.Status));
                pnlEntering.Visible = false;
                return;
            }

            txtYear.Value = pd.date_of_birth.Year.ToString();
            txtDay.Value = pd.date_of_birth.Day.ToString();
            txtFirstName.Value = pd.first_name;
            txtLastName.Value = pd.last_name;
            txtInterests.Value = pd.interests;
            txtBio.Value = pd.bio;
            txtICQ.Value = pd.icq;
            txtPhone.Value = pd.phone_number;
            txtJabber.Value = pd.jabber;
            txtChest.Value = pd.chest.ToString();
            txtWaist.Value = pd.waist.ToString();
            txtHip.Value = pd.hip.ToString();
            txtHeight.Value = pd.u_height.ToString();
            txtWeight.Value = pd.u_weight.ToString();

            switch (pd.gender) {
                case 0:
                    optMale.Checked = true;
                    break;
                case 1:
                    optFemale.Checked = true;
                    break;
                case 2:
                    optInter.Checked = true;
                    break;
            }
            cboMonth.Value = pd.date_of_birth.Month.ToString();
            cboOrientation.Value = pd.orientation.ToString();
            cboReason.Value = pd.reason.ToString();

            if (pd.hair_color.HasValue) {
                cboHairColor.Value = pd.hair_color.ToString();
            }
            if (pd.eye_color.HasValue) {
                cboEyeColor.Value = pd.eye_color.ToString();
            }
            if (pd.main_size.HasValue) {
                cboMainSize.Value = pd.main_size.ToString();
            }

            // zodiac:
            hfZSign.Value = pd.zodiac.ToString();
        }

        private string filterTags(string text) {
            // SORTED! array of valid tags
            string[] VALID_ELEMENTS = { "b", "br", "em", "i", "li", "ol", "p", "strong", "ul" };
            StringComparer strComp = StringComparer.Create(CultureInfo.InvariantCulture, true);

            int startTag = -1;
            List<string> tagsToDelete = new List<string>();
            while (true) {
                startTag = text.IndexOf("<", startTag + 1);
                if (startTag == -1) break;
                int endTag = text.IndexOf(">", startTag);

                string tagName = text.Substring(startTag + 1, endTag - startTag - 1);
                if (tagName.StartsWith("/")) tagName = tagName.Substring(1);

                if (Array.BinarySearch<string>(VALID_ELEMENTS, tagName, 
                    strComp) == -1) {
                    tagsToDelete.Add(tagName);
                }
            };

            foreach (string tagName in tagsToDelete) {
                text = Regex.Replace(text, @"\</*" + Regex.Escape(tagName) + @"\>",
                    "", RegexOptions.IgnoreCase);
            }

            return text;
        }

        protected void cmdSave_Click(object sender, EventArgs e) {
            // re-read PD
            ResultWithStatusOfstring resGetPd = Client.GetPersonalData(SessionKeyHash);

            if (Status.SUCCESS(resGetPd.Status)) {
                pd = CryptoImpl.readObjectEncrypted<SmartDatingRef.PersonalData>(
                    b(resGetPd.Result), b(SessionKey));
            } else if (resGetPd.Status == OperationStatus.NoPersonalData) {
                pd = new PersonalData();
            } else {
                Utils.showError(errSpan, Status.m(resGetPd.Status));
                return;
            }

            // set relevant data in the PD
            pd.bio = filterTags(txtBio.Value);
            pd.interests = txtInterests.Value;

            if (txtFirstName.Value.Trim().Length == 0) {
                Utils.showError(errSpan, "Не введено имя.");
                return;
            }
            pd.first_name = txtFirstName.Value;

            if (txtLastName.Value.Trim().Length == 0) {
                pd.last_name = null;
            } else {
                pd.last_name = txtLastName.Value;
            }

            DateTime dr;
            if (!DateTime.TryParse(txtYear.Value + "-" + cboMonth.Value + "-" + txtDay.Value,
                new CultureInfo("en-US"), DateTimeStyles.None, out dr)) {

                Utils.showError(errSpan, "Введена некорректная дата рождения");
                return;
            }
            
            TimeSpan ts = DateTime.Now.ToUniversalTime() - dr.ToUniversalTime();
            const double YEAR_CALC = 365.2425;
            if ( (int)Math.Floor( ((double)ts.Days) / YEAR_CALC) < 18 ) {                
                Utils.showError(errSpan, "Введена некорректная дата рождения");
                return;
            }
            pd.date_of_birth = new DateTime(int.Parse(txtYear.Value), int.Parse(cboMonth.Value), int.Parse(txtDay.Value));

            pd.gender = int.Parse(Request[optMale.Parent.UniqueID + "$optGender"]);
            pd.orientation = int.Parse(cboOrientation.Value);
            pd.reason = int.Parse(cboReason.Value);
            pd.zodiac = int.Parse(Request["optZodiac"]);

            pd.phone_number = txtPhone.Value;
            pd.icq = txtICQ.Value;
            pd.jabber = txtJabber.Value;

            if (cboHairColor.Value != "-1") {
                pd.hair_color = int.Parse(cboHairColor.Value);
            } else {
                pd.hair_color = null;
            }
            if (cboEyeColor.Value != "-1") {
                pd.eye_color = int.Parse(cboHairColor.Value);
            } else {
                pd.eye_color = null;
            }
            if (cboMainSize.Value != "-1") {
                pd.main_size = int.Parse(cboMainSize.Value);
            } else {
                pd.main_size = null;
            }

            int chest = -1, waist = -1, hip = -1;
            if ((txtChest.Value != "" && !int.TryParse(txtChest.Value, out chest)) ||
                (txtWaist.Value != "" && !int.TryParse(txtWaist.Value, out waist)) ||
                (txtHip.Value != "" && !int.TryParse(txtHip.Value, out hip))) {

                Utils.showError(errSpan, "Введены некорректные пропорции.");
                return;
            }
            pd.chest = txtChest.Value == "" ? (int?)null : chest;
            pd.waist = txtWaist.Value == "" ? (int?)null : waist;
            pd.hip = txtHip.Value == "" ? (int?)null : hip;

            OperationStatus resSavePd = Client.SetPersonalData(SessionKeyHash,
                s(CryptoImpl.writeObjectEncrypted<PersonalData>(
                    pd, b(SessionKey))));
            if (!Status.SUCCESS(resSavePd)) {
                Utils.showError(errSpan, Status.m(resSavePd));
                return;
            }

            Response.Redirect(Request.Params["ReturnUrl"] != null ?
                Request.Params["ReturnUrl"] :
                "Dashboard.aspx");
        }
    }
}